package cn.com.connext.scrm.service;

import cn.com.connext.scrm.domain.enumeration.MemberStatus;
import cn.com.connext.scrm.domain.master.InteractiveRecord;
import cn.com.connext.scrm.domain.master.Member;
import cn.com.connext.scrm.domain.master.Note;
import cn.com.connext.scrm.repository.master.InteractiveRecordRepository;
import cn.com.connext.scrm.repository.master.MemberRepository;
import cn.com.connext.scrm.repository.master.NoteRepository;
import cn.com.connext.scrm.service.dto.InteractiveRecordDTO;
import cn.com.connext.scrm.service.mapper.InteractiveRecordMapper;
import cn.com.connext.scrm.web.rest.errors.MyErrorCode;
import com.connext.common.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class InteractiveRecordService extends BaseService<InteractiveRecord, String> {

    private final Logger log = LoggerFactory.getLogger(InteractiveRecordService.class);

    private final InteractiveRecordRepository interactiveRecordRepository;

    @Autowired
    private InteractiveRecordMapper interactiveRecordMapper;

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private NoteRepository noteRepository;

    public InteractiveRecordService(InteractiveRecordRepository interactiveRecordRepository) {
        super(interactiveRecordRepository);
        this.interactiveRecordRepository = interactiveRecordRepository;
    }

    /**
     * 构建查询条件
     *
     * @param interactiveRecordDTO
     * @param strings
     * @return
     */
    public Specification<InteractiveRecord> getWhereClause(final InteractiveRecordDTO interactiveRecordDTO, List<String> strings) {
        Specification<InteractiveRecord> specification = (Root<InteractiveRecord> root, CriteriaQuery<?> query,
                                                          CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotEmpty(interactiveRecordDTO.getReceiveUserId())) {
                Predicate lineFactoryEqual_add = cb.equal(root.get("receiveUserId"), interactiveRecordDTO.getReceiveUserId());
                predicates.add(lineFactoryEqual_add);
                Predicate lineFactoryNotEqual_add = cb.notEqual(root.get("userId"), interactiveRecordDTO.getReceiveUserId());
                predicates.add(lineFactoryNotEqual_add);
            }
//            if (null != interactiveRecordDTO.getInteractiveType() && StringUtils.isNotEmpty(interactiveRecordDTO.getInteractiveType().toString())) {
//                if (0 == interactiveRecordDTO.getInteractiveType()) {
//                    Predicate lineFactoryEqual_add = cb.equal(root.get("interactiveType"), 0);
//                    predicates.add(lineFactoryEqual_add);
//                } else {
//                    Predicate lineFactoryNotEqual_add = cb.notEqual(root.get("interactiveType"), 0);
//                    predicates.add(lineFactoryNotEqual_add);
//                }
//
//            }
            if (null != interactiveRecordDTO.getInteractiveType() && StringUtils.isNotEmpty(interactiveRecordDTO.getInteractiveType().toString())) {
                Predicate lineFactoryEqual_add = cb.equal(root.get("interactiveType"), interactiveRecordDTO.getInteractiveType());
                predicates.add(lineFactoryEqual_add);
            }
            if (null != strings && strings.size() > 0) {
                CriteriaBuilder.In<String> in = cb.in(root.get("noteId"));
                for (String id : strings) {
                    in.value(id);
                }
                predicates.add(in);
            }
            query.orderBy(cb.desc(root.get("createTime").as(ZonedDateTime.class)));
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }


    public void  deleteInteractiveRecordByNoteId(String  noteId){
        interactiveRecordRepository.closeInteractiveRecordByNoteId(noteId);
    }
    /**
     * 我的互动
     *
     * @param pageable
     * @param userId
     * @param kind     0：受邀回答 1：收到的评论 2：收到的点赞
     * @return
     */
    public Page<InteractiveRecordDTO> getMyInteraction(Pageable pageable, String userId, Integer kind) {
        Member member = memberRepository.findOneByUnionId(userId);
        if (null == member) {
            throw new ServiceException(MyErrorCode.ERROR_MEMBER_NOT_EXIST);
        }
        InteractiveRecordDTO interactiveRecordDTO = new InteractiveRecordDTO();
        interactiveRecordDTO.setReceiveUserId(userId);
        interactiveRecordDTO.setInteractiveType(kind);

        List<String> list = noteRepository.findAllNoteIdWithoutDelete();

        Page<InteractiveRecord> page = interactiveRecordRepository.findAll(getWhereClause(interactiveRecordDTO, list), pageable);
        return page.map(interactiveRecord -> interactiveRecordMapper.toDto(interactiveRecord));

//        //region 返回DTO
//        List<InteractiveRecord> interactiveRecordList = interactiveRecordRepository.findAll(getWhereClause(interactiveRecordDTO));
//        List<InteractiveRecordDTO> list = interactiveRecordMapper.toDto(interactiveRecordList);
//        List<InteractiveRecordDTO> newResult = new ArrayList<InteractiveRecordDTO>();
//        int currIdx = (pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageable.getPageSize() : 0);
//        for (int i = 0; i < pageable.getPageSize() && i < list.size() - currIdx; i++) {
//            InteractiveRecordDTO report = list.get(currIdx + i);
//            newResult.add(report);
//        }
//        Pageable pageable2 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize());
//        Page pageResult = new PageImpl(newResult, pageable2, list.size());
//
//        Page<InteractiveRecordDTO> notePage = pageResult;
//
//        return notePage;
//        //endregion
    }


    /**
     * 更新互动状态（是否查看）
     *
     * @param id
     */
    public void updateStatus(String id) {
        InteractiveRecord interactiveRecord = interactiveRecordRepository.findOne(id);
        if (null == interactiveRecord) {
            throw new ServiceException(MyErrorCode.ERROR_INTERACTION_NOT_EXIST);
        }
        if (false == interactiveRecord.getLookup()) {
            interactiveRecord.setLookup(true);
        }
    }

    public  void clearLikeRedDot(String userId){
        interactiveRecordRepository.clearLikeRedDot(userId);
    }

    /**
     * 添加一条互动记录
     *
     * @param noteId          帖子Id
     * @param userId          发起人Id
     * @param receiveUserId   接收人Id
     * @param interactiveType 互动类型（0：邀请回答，1：评论，2：点赞）
     * @param type            互动发生的场景（0：帖子，1：评论）
     * @param createTime      互动发生的时间
     */
    public String create(String noteId, String userId, String receiveUserId, Integer interactiveType, Integer type, ZonedDateTime createTime) {
        if (1 == type && (StringUtils.isEmpty(noteId) || StringUtils.isEmpty(userId) || StringUtils.isEmpty(receiveUserId)
            || null == interactiveType || null == type)) {
            return "互动记录参数错误";
        }
        if (0 == type && (StringUtils.isEmpty(noteId) || StringUtils.isEmpty(userId))) {
            return "互动记录参数错误";
        }
        Member member = memberRepository.findOneByUnionId(userId);
        if (null == member) {
            throw new ServiceException(MyErrorCode.ERROR_MEMBER_NOT_EXIST);
        }
        String userName = member.getNickName();
        Note note = noteRepository.findOne(noteId);
        if (null == note) {
            throw new ServiceException(MyErrorCode.ERROR_NOTE_NOT_EXIST);
        }
        String noteTitle = note.getTitle();
        InteractiveRecord interactiveRecord = new InteractiveRecord();
        interactiveRecord.setNoteId(noteId);
        interactiveRecord.setUserId(userId);
        interactiveRecord.setReceiveUserId(receiveUserId);
        interactiveRecord.setInteractiveType(interactiveType);
        interactiveRecord.setLookup(false);
        interactiveRecord.setCreateTime(createTime);
        String content = "";
        switch (interactiveType) {
            case 0:
                content = userName + "邀请你回答：" + noteTitle;
                break;
            case 1:
                if (0 == type) {
                    content = userName + "评论了你的笔记";
                }
                if (1 == type) {
                    content = userName + "回复了你的评论";
                }
                break;
            case 2:
                if (0 == type) {
                    content = userName + "赞了你的笔记";
                }
                if (1 == type) {
                    content = userName + "赞了你的评论";
                }
                break;
            default:
        }
        interactiveRecord.setContent(content);
        interactiveRecordRepository.save(interactiveRecord);
        return "成功创建一条互动记录!";
    }

    /**
     * 添加一条互动记录（改）
     *
     * @param interactiveRecordDTO
     * @return
     */
    public String createNew(InteractiveRecordDTO interactiveRecordDTO) {
        String userId = interactiveRecordDTO.getUserId();
        Member member = memberRepository.findOneByUnionId(userId);
        if (null == member) {
            return "用户不存在！";
        }

        String noteId = interactiveRecordDTO.getNoteId();
        Note note = noteRepository.findOne(noteId);
        if (null == note) {
            return "帖子不存在！";
        }

        if (null == interactiveRecordDTO.getLookup()) {
            interactiveRecordDTO.setLookup(false);
        }

        interactiveRecordDTO.setContent(interactiveRecordDTO.getContent() == null ? "" : interactiveRecordDTO.getContent());

        InteractiveRecord interactiveRecord = interactiveRecordMapper.toEntity(interactiveRecordDTO);
        interactiveRecordRepository.save(interactiveRecord);
        return "成功创建一条互动记录!";
    }

    /**
     * 删除一条互动记录
     *
     * @param noteId
     * @param userId
     * @param receiveUserId
     * @param interactiveType
     */
    public String delete(String noteId, String userId, String receiveUserId, Integer interactiveType) {
        if (StringUtils.isEmpty(noteId) || StringUtils.isEmpty(userId) || StringUtils.isEmpty(receiveUserId)
            || null == interactiveType) {
            return "互动记录参数错误";
        }
        InteractiveRecord interactiveRecord = interactiveRecordRepository.findOneByNoteIdAndUserIdAndReceiveUserIdAndInteractiveType(noteId, userId, receiveUserId, interactiveType);
        if (null != interactiveRecord) {
            interactiveRecordRepository.delete(interactiveRecord);
            return "成功删除一条互动记录!";
            //throw new ServiceException(MyErrorCode.ERROR_INTERACTION_NOT_EXIST);
        } else {
            return "互动记录不存在，无法删除。";
        }
    }

    /**
     * 根据unionId查询我的互动里面尚未查看的记录
     *
     * @param unionId
     * @return
     */
    public Integer queryUnLookUpByUnionId(String unionId) {
        Member member = memberRepository.findOneByUnionId(unionId);
        if (null == member || member.getStatus() == MemberStatus.DELETED) {
            return 0;
        } else {

            Integer count = interactiveRecordRepository.countAllByReceiveUserIdAndIsLookup(unionId, false);
            Integer my_count = interactiveRecordRepository.countAllByUserIdAndReceiveUserIdAndIsLookup(unionId, unionId, false);
            count = count - my_count;
            return count == null ? 0 : count;
        }
    }


    /**
     * 根据unionId和type查询我的互动里面尚未查看的记录
     *
     * @param unionId
     * @param type
     * @return
     */
    public Integer queryUnLookUpByUnionIdAndType(String unionId, Integer type) {
        Member member = memberRepository.findOneByUnionId(unionId);
        if (null == member || member.getStatus() == MemberStatus.DELETED
            || StringUtils.isEmpty(type.toString())) {
            return 0;
        } else {
            Integer count = interactiveRecordRepository.countAllByReceiveUserIdAndInteractiveTypeAndIsLookup(unionId, type, false);
            Integer my_count = interactiveRecordRepository.countAllByUserIdAndReceiveUserIdAndInteractiveTypeAndIsLookup(unionId, unionId, type, false);
            count = count - my_count;
            return count == null ? 0 : count;
        }
    }

    public Integer queryUnLookUpExceptLikes(String unionId, Integer type) {
        Member member = memberRepository.findOneByUnionId(unionId);
        if (null == member || member.getStatus() == MemberStatus.DELETED
            || StringUtils.isEmpty(type.toString())) {
            return 0;
        } else {
            Integer count = 0;
            count = interactiveRecordRepository.countAllInteractionExceptLikes(unionId, unionId, type, false);
            return count >= 0 ? count : 0;
        }
    }
}
